import json

import cv2
import numpy as np

from tools.constant.redis_keys import ALGO_RUN_MODEL, ALGO_INPUT_IMG_OP_PRE
from tools.constant.config_key import CAMERA_KEY
from tools.constant.redis_keys import ALGO_CONFIG_KEY, ALGO_LOAD_MODEL
from tools.utils.ip_util import get_ip_address_by_nic
from tools.utils.redis_client import redis_client_instance




def read_img_from_redis(redis_client=redis_client_instance(), config=None, start=0, end=0, order_by_ts=True):
    """
    从Redis中读取图像数据。
    本函数通过配置参数获取指定摄像头的图像集合，并可以根据时间戳对图像进行排序。

    参数:
    - redis_client: Redis客户端实例，默认为创建一个新的实例。
    - config: 包含摄像头信息的配置字典，用于确定要读取的图像集合。
    - start: 图像集合中开始读取的位置，默认为0。
    - end: 图像集合中结束读取的位置，默认为0。
    - order_by_ts: 是否根据时间戳对图像进行排序，默认为True。

    返回:
    - 成功时返回一个包含图像和时间戳信息的列表，每个元素为(img, int(ts100 / 100), ts100 % 100, ts100)。
    - 如果config为空，则返回None。
    """
    # 初始化结果列表
    res = []

    # 检查是否提供了配置信息
    if config:
        # 从Redis中读取指定摄像头的图像集合
        images_zset = redis_client.zrange(config[CAMERA_KEY], start, end, withscores=order_by_ts)

        # 遍历图像集合，处理每个图像和它的时间戳
        for (img, ts100) in images_zset:
            # 将图像和时间戳信息添加到结果列表中
            orgein_ts = ts100
            try:
                if len(str(int(ts100))) == 13:
                    # 毫秒级
                    ts100 = int(ts100/1000)
                else:
                    ts100 = int(ts100/100)
            except Exception as e:
                ts100 = int(ts100)
            res.append((img, ts100, ts100 % 100, orgein_ts))

        # 返回处理后的图像和时间戳信息列表
        return res
    else:
        # 如果没有提供配置信息，返回None
        return None



def run_with_model(algo_name,run_flag=0, redis_client=redis_client_instance()):
    """
    设置算法是否

    该函数从Redis客户端读取算法配置，检查算法是否支持使用现有模型运行。

    参数:
    algo_name (str): 算法名称，用于读取对应的配置。
    redis_client: Redis 客户端实例，默认为预定义实例。用于读取算法配置。

    返回:
    bool: 如果配置表明算法应使用现有模型运行，则返回 True；否则返回 False。
    """
    # 从 Redis 读取算法配置
    redis_client.hset(ALGO_RUN_MODEL, algo_name, run_flag)

def run_with_model_status(algo_name,redis_client=redis_client_instance()):
    """
    算法是否开启加载模型

    返回:
    bool: 加载模型 True；否则返回 False。
    """
    # 从 Redis 读取算法配置
    flag = redis_client.hget(ALGO_LOAD_MODEL, algo_name)
    if flag is None:
        return False
    else:
        st = redis_client.hget(ALGO_LOAD_MODEL, algo_name)
        if st:
            return int(st.decode("utf-8"))>0
        else:
            return False


def load_model_status(algo_name, redis_client=redis_client_instance()):
    """
    加载模型状态

    此函数用于检查给定算法模型的加载状态。它通过Redis客户端从Redis哈希中获取状态标志，并返回一个布尔值，指示模型是否已加载。

    :param algo_name: 算法名称，用于在Redis中查找对应的加载状态
    :param redis_client: Redis客户端实例，默认为全局的redis_client_instance实例
    :return: 如果模型已加载，返回True；否则返回False
    """
    # 获取 Redis 中的值
    # vs = redis_client.hget(ALGO_RUN_MODEL,algo_name)
    # if vs:
    #     redis_client.hset(ALGO_LOAD_MODEL, algo_name,vs)
    value = redis_client.hget(ALGO_LOAD_MODEL, algo_name)

    # 检查 value 是否为 None
    if value is None:

        flag = False
    else:
        flag = int(value.decode("utf-8"))

    return flag > 0



def set_model_status(algo_name, flag=0, redis_client=redis_client_instance()):
    """
    设置模型加载状态。

    本函数通过Redis客户端更新指定算法模型的加载状态。状态标志由`flag`参数指定，默认为0，
    表示未加载。这提供了一种标记算法模型加载状态的灵活方式，便于系统跟踪和管理。

    参数:
    - algo_name (str): 算法模型的名称，用于在Redis中标识模型。
    - flag (int, 可选): 模型加载状态的标志，0表示未加载，非零值可自定义为加载或其他状态。
    - redis_client (object, 可选): Redis客户端实例，默认为全局的`redis_client_instance()`。
        这允许函数在调用时使用不同的Redis连接实例。

    返回:
    无返回值。函数执行结果是Redis中指定模型状态的更新。
    """
    # redis_client.hset(ALGO_LOAD_MODEL, algo_name, flag)
    redis_client.hset(ALGO_RUN_MODEL, algo_name, flag)


import os
from pathlib import Path

def save_algo_result_img(algo_name, img_data,img_id):
    try:
    # 从环境变量中读取 SAVE_IMG_PATH
        save_path = os.getenv('SAVE_IMG_PATH', '~/img_data/')
        # 将路径转换为绝对路径
        save_path = Path(save_path).expanduser().resolve()
        # 创建算法结果文件夹
        algo_dir = save_path / algo_name
        if not algo_dir.exists():
            algo_dir.mkdir(parents=True, exist_ok=True)
        # 构建图像文件路径
        img_file_path = algo_dir / f'{img_id}.jpg'
        # 检查文件是否已经存在
        if img_file_path.exists():
            print(f"File {img_file_path} already exists, skipping save.")
            # return str(img_file_path)
        # 保存图像数据
        with open(img_file_path, 'wb') as img_file:
            img_file.write(img_data)
    except FileNotFoundError as e:
        print(f"FileNotFoundError: {e}")
    except PermissionError as e:
        print(f"PermissionError: {e}")
    except OSError as e:
        print(f"OSError: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    #获取本机ip
    return f"http://{get_ip_address_by_nic(None)}/images/{algo_name}/{img_id}.jpg"

def get_algo_input_img(algo_name,redis_client=redis_client_instance()):
    redis_client.hget(ALGO_INPUT_IMG_OP_PRE+algo_name)
    return redis_client.hget(ALGO_INPUT_IMG_OP_PRE+algo_name)

def get_upload_interest(redis_client=redis_client_instance()):
    hash_all = redis_client.hgetall("algo:upload:interest")
    res = []
    if hash_all:
        for k,v in hash_all.items():
            res.append({
                "id":k.decode("utf-8")[:-3],
                "op":k.decode("utf-8")[-3:],
                "img":v
            })
        return res
    else:
        return None

def clean_upload_interest(redis_client=redis_client_instance()):
    redis_client.delete("algo:upload:interest")



def update_algo_description(algo_name,
                            algo_show_name,
                            algo_icon="defaut.icon",
                            algo_args={},
                            bus_args={},redis_client=redis_client_instance()):
    """
    更新算法描述信息。

    该函数用于更新或初始化算法的配置信息，包括算法名称、显示名称、图标以及相关参数。
    它将这些信息存储在Redis中，以便在系统中共享和使用。

    参数:
    algo_name (str): 算法的唯一名称，用于标识算法。
    algo_show_name (str): 算法的显示名称，如果未提供，则使用algo_name。
    algo_icon (str): 算法的图标路径，默认为"default.icon"。
    algo_args (dict): 算法的具体参数字典，默认为空字典。
    bus_args (dict): 与算法相关的业务参数字典，默认为空字典。
    redis_client: Redis客户端实例，默认为redis_client_instance()。

    返回:
    无
    """
    if algo_show_name is None:
        algo_show_name = algo_name
    algo_config_args = {
         "@class": "java.lang.Object",
        "algo_name": algo_name,
        "algo_show_name": algo_show_name,
        "algo_icon": algo_icon,
        "algo_args": algo_args,
        "bus_args": bus_args
    }
    redis_client.hset(ALGO_CONFIG_KEY, algo_name,json.dumps(algo_config_args).encode("utf-8"))


if __name__ == "__main__":
    pass
    st = read_img_from_redis(config={
        CAMERA_KEY:'camera:frames:1838502535022682114'
    },start=0,end=0)


    for _,y,z,t in st:
        print(17344168075)
        print(17344168075)
        print(1734416837)
        # print(1734416815)
        print(y,z,t)
        #print(len(x))
    # print(json.loads(redis_client_instance().hget("algo:config:SAFETY_HELMET_WEARING_DETECTION","1").decode("utf-8")))
    # print(update_algo_description("sdfsdfsdfsdf","12121211212"))
    # save_algo_result_img("fet",b'123',1)